package com.example.kotlinstudy.类与对象

//扩展函数
fun <T> MutableList<T>.swap(index1: Int, index2: Int) {
    val tmp = this[index1]
    this[index1] = this[index2]
    this[index2] = tmp;
}

fun main() {
    val list = mutableListOf(1, 2, 3)
    list.swap(0, 2)
    ///扩展是静态解析的
    open class Shape
    class Rectangle : Shape()

    fun Shape.getName() = "Shape"
    fun Rectangle.getName() = "Rectangle"
    fun printClassName(s: Shape) {
        println(s.getName())
    }
    printClassName(Rectangle())

    ///扩展函数与组内函数名一致时取组内函数
    class Example {
        fun printA() {
            println("A")
        }
    }

    fun Example.printA() {
        println("a")
    }
    Example().printA()

    ///重载函数不同签名成员函数
    class Example1 {
        fun printB() {
            println("B")
        }
    }

    fun Example1.printB(i: Int) {
        println("$i")
    }
    Example1().printB(1);

    ///可空接受者
    fun Any?.toString(): String {
        if (this == null) return "null"
        return toString()
    }

    //伴生对象的扩展
    MyClass.printCompanion()

    ///扩展的作用域
    val listA = listOf<String>("red", "green", "blue")
    listA.getLongestString()

    ///扩展声明为成员
    Connection(Host("kotl.in"), 443).connect()

    BaseCaller().call(Base3())   // “Base extension function in BaseCaller”
    DerivedCaller().call(Base3())  // “Base extension function in DerivedCaller”——分发接收者虚拟解析
    DerivedCaller().call(Derived3())  // “Base extension function in DerivedCaller”——扩展接收者静态解析
}

//扩展属性
val <T> List<T>.lastIndex: Int
    get() = size - 1

//伴生对象的扩展
class MyClass {
    companion object
}

fun MyClass.Companion.printCompanion() {
    println("companion")
}

///扩展声明为成员
class Host(val hostname: String) {
    fun printHostname() {
        print(hostname)
    }
}

class Connection(val host: Host, val port: Int) {
    fun printPort() {
        print(port)
    }

    fun Host.printConnectionString() {
        printHostname()
        print(":")
        printPort()
    }

    fun connect() {
        host.printConnectionString()
    }

    fun Host.getConnectionString() {
        toString() //调用Host.toString()
        this@Connection.toString() //调用Connection.toString()
    }
}

///
open class Base3 {

}

class Derived3 : Base3() {

}

open class BaseCaller {
    open fun Base3.printFunctionInfo() {
        println("Base extension function in BaseCaller")
    }

    open fun Derived3.printFunctionInfo() {
        println("Derived extension function in BaseCaller")
    }

    fun call(b: Base3) {
        b.printFunctionInfo()
    }
}

class DerivedCaller : BaseCaller() {
    override fun Base3.printFunctionInfo() {
        println("Base extension function in DerivedCaller")
    }

    override fun Derived3.printFunctionInfo() {
        println("Derived extension function in DerivedCaller")
    }
}
